package com.junzhiit.nengji.cms.web.util.erpt;

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.bainaeco.framework.util.HttpClientUtils;
import com.bainaeco.framework.util.JsonUtil;
import com.junzhiit.nengji.bo.PrinterAccessTokenVO;
import com.junzhiit.nengji.cms.web.exception.YiLianYunException;
import com.junzhiit.nengji.cms.web.util.erpt.bean.ResultBody;
import com.junzhiit.nengji.cms.web.util.erpt.bean.ResultData;
import com.junzhiit.nengji.cms.web.util.erpt.bean.ResultError;
import com.junzhiit.nengji.cms.web.util.erpt.bean.enums.ResultErrorStatus;
import com.junzhiit.nengji.dao.cache.PrinterCacheDAO;
import com.junzhiit.nengji.dao.util.DIYKey;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;

@Component
public class PrintMessageUtils {
	//log日志
	private static Logger logger = Logger.getLogger(PrintMessageUtils.class);
	
	
	public static PrinterCacheDAO printerCacheDAO;
    
	@Autowired
	public void setPrinterCacheDAO(PrinterCacheDAO printerCacheDAO) {
		PrintMessageUtils.printerCacheDAO = printerCacheDAO;
	}
	

	/**
	 * 打印签名
	 * @param params
	 * @return
	 */
	public static String signRequest(long timestamp){
		StringBuilder query=new StringBuilder();
		query.append(ApiConstants.CLIENT_ID);
		query.append(timestamp);
		query.append(ApiConstants.CLIENT_SECRET);
		String encryptStr=MD5.MD5Encode(query.toString()).toLowerCase();
		return encryptStr;
	}
	


	/**
	 * 
	 * TODO 获取UUID
	 * @author FEB
	 * @time 2018年9月6日 下午9:33:56
	 * @return String
	 */
	public static String getUUID(){
		return UUID.randomUUID().toString();
	}
	
	/**
	 * 
	 * TODO 10位时间戳
	 * @author FEB
	 * @time 2018年9月7日 下午3:46:48
	 * @return Long
	 */
	public static Long getTimestamp(){
		return new Date().getTime()/1000;
	}
	
	/**
	 * 
	 * TODO 设置统一参数
	 * @author FEB
	 * @time 2018年9月7日 下午3:46:39
	 * @return void
	 */
	public static void setParams(Map<String,String> params){
		Long timestamp=getTimestamp();
		params.put(ApiConstants.CLIENT_ID_PARAM_NAME, ApiConstants.CLIENT_ID);
		params.put(ApiConstants.SIGN_PARAM_NAME, signRequest(timestamp));
		params.put(ApiConstants.TIMESTAMP_PARAM_NAME, timestamp.toString());
		params.put(ApiConstants.ID_PARAM_NAME, getUUID());
	}
	
	public static ResultError parseResultError(String json){
		ResultError resultError=new ResultError();
		
		ObjectMapper mapper = new ObjectMapper();
        mapper.setPropertyNamingStrategy(PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES);
        
        try {
			resultError = mapper.readValue(json,ResultError.class);
		} catch (IOException e) {
			e.printStackTrace();
		}
        
        ResultErrorStatus error = ResultErrorStatus.getError(resultError.getError());
//      if(error.toIntStatus()==ResultErrorStatus.ACCESS_TOKEN_EXPIRED.toIntStatus()){
//    		printerCacheDAO.del(DIYKey.getPrinterAccessTokenKey());
//    	}
        if(error != null && error.toIntStatus()!=ResultErrorStatus.SUCCESS.toIntStatus()) {
        	throw new YiLianYunException(error.toIntStatus(), error.toStringValue());
        }
        return resultError;
	}
	
	public static void setAccessTokenCache(ResultBody resultBody){
		String key=DIYKey.getPrinterAccessTokenKey();
		PrinterAccessTokenVO printerAccessTokenVO=new PrinterAccessTokenVO();
		printerAccessTokenVO.setAccessToken(resultBody.getAccessToken());
		printerAccessTokenVO.setTime(new Date().getTime()+(resultBody.getExpiresIn()*1000L));
		printerAccessTokenVO.setRefreshToken(resultBody.getRefreshToken());
		printerCacheDAO.addString(key, printerAccessTokenVO.toString());
	}
	
	/**
	 * 
	 * TODO 获得access_token
	 * @author FEB
	 * @time 2018年9月6日 下午11:39:11
	 * @return String
	 */
	public static String getAccessToken(){
		String result=null;
		
		String key=DIYKey.getPrinterAccessTokenKey();
		String json=printerCacheDAO.getString(key);
		PrinterAccessTokenVO printerAccessTokenVO=JsonUtil.toObject(json, PrinterAccessTokenVO.class);
		
		if(printerAccessTokenVO==null){
			ResultBody resultBody=getAccessTokenRequest();
			result=resultBody.getAccessToken();
			
			//redis cache
			setAccessTokenCache(resultBody);
			
		}else{
			if(printerAccessTokenVO.getTime()<=new Date().getTime()){
				ResultBody resultBody=updateAccessToken(printerAccessTokenVO.getRefreshToken());
				
				//redis cache
				setAccessTokenCache(resultBody);
			}
			
			result=printerAccessTokenVO.getAccessToken();
		}
		
		return result;
	}
	
	
	public static ResultBody getAccessTokenRequest(){
		ResultBody resultBody=new ResultBody();
		
		Map<String,String> params=new HashMap<String,String>();
		params.put(ApiConstants.GRANT_TYPE_PARAM_NAME, ApiConstants.GRANT_TYPE);
		params.put(ApiConstants.SCOPE_PARAM_NAME, ApiConstants.SCOPE);
		setParams(params);
		
		String result=null;
		try {
			result=HttpClientUtils.postMethodRequest(ApiConstants.ACCESS_TOKEN_URL, params);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		resultBody=parseJson(result);
		
		return resultBody;
	}
	
	public static ResultBody parseJson(String json){
		ResultBody resultBody=null;
		
		if(StringUtils.isNotBlank(json)){
			ObjectMapper mapper = new ObjectMapper();
	        mapper.setPropertyNamingStrategy(PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES);
	        ResultData data=null;
			try {
				data = mapper.readValue(json,ResultData.class);
				if(data.getError()==ResultErrorStatus.SUCCESS.toIntStatus()){
					resultBody=data.getBody();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
		return resultBody;
	}
	
	
	/**
	 * 
	 * TODO 更新access_token
	 * @author FEB
	 * @time 2018年9月6日 下午11:38:55
	 * @return String
	 */
	public static ResultBody updateAccessToken(String refreshToken){
		ResultBody resultBody=new ResultBody();
		
		Map<String,String> params=new HashMap<String,String>();
		params.put(ApiConstants.GRANT_TYPE_PARAM_NAME, ApiConstants.GRANT_TYPE);
		params.put(ApiConstants.SCOPE_PARAM_NAME, ApiConstants.SCOPE);
		params.put(ApiConstants.REFRESH_TOKEN_PARAM_NAME, refreshToken);
		setParams(params);
		
		String json=null;
		try {
			json=HttpClientUtils.postMethodRequest(ApiConstants.ACCESS_TOKEN_URL, params);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		resultBody=parseJson(json);
		
		return resultBody;
	}
	
	/**
	 * 
	 * TODO 添加打印机
	 * @author FEB
	 * @time 2018年9月6日 下午11:38:42
	 * @return String
	 * @throws Exception 
	 */
	public static ResultError addPrinterRequest(String machineCode,String msign,String phone,String printName){
		
		Map<String,String> params=new HashMap<String,String>();
		params.put(ApiConstants.MACHINE_CODE_PARAM_NAME, machineCode);
		params.put(ApiConstants.MSIGN_PARAM_NAME, msign);
		params.put(ApiConstants.ACCESS_TOKEN_PARAM_NAME,getAccessToken());
		params.put(ApiConstants.PHONE_PARAM_NAME, phone);
		params.put(ApiConstants.PRINT_NAME_PARAM_NAME, printName);
		setParams(params);
		
		String result=null;
		try {
			result=HttpClientUtils.postMethodRequest(ApiConstants.ADD_PRINTER_URL, params);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		ResultError resultError=parseResultError(result);
		logger.info("error:"+resultError.getError()+" error_description:"+resultError.getErrorDescription());
		
		return resultError;
	}
	
	/**
	 * 
	 * TODO 打印终端设备
	 * @author FEB
	 * @time 2018年9月6日 下午11:38:27
	 * @return String
	 */
	public static ResultError sendPrintRequest(String machineCode,String content,String originId){
		
		Map<String,String> params=new HashMap<String,String>();
		params.put(ApiConstants.MACHINE_CODE_PARAM_NAME, machineCode);
		params.put(ApiConstants.ACCESS_TOKEN_PARAM_NAME,getAccessToken());
		params.put(ApiConstants.CONTENT_PARAM_NAME, content);
		params.put(ApiConstants.ORIGIN_ID_PARAM_NAME,originId);
		setParams(params);
		
		String result=null;
		try {
			result=HttpClientUtils.postMethodRequest(ApiConstants.SEND_PRINT_URL, params);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		ResultError resultError=parseResultError(result);
		logger.info("error:"+resultError.getError()+" error_description:"+resultError.getErrorDescription());
		
		return resultError;
	}
	
	
	public static ResultError setVoiceRequest(String machineCode,String content,Boolean isFile,Integer aid){
		
		Map<String,String> params=new HashMap<String,String>();
		params.put(ApiConstants.MACHINE_CODE_PARAM_NAME, machineCode);
		params.put(ApiConstants.ACCESS_TOKEN_PARAM_NAME,getAccessToken());
		params.put(ApiConstants.CONTENT_PARAM_NAME, content);
		params.put(ApiConstants.ISFILE_PARAM_NAME, isFile.toString());
		params.put(ApiConstants.AID_PARAM_NAME, aid.toString());
		setParams(params);
		
		String result=null;
		try {
			result=HttpClientUtils.postMethodRequest(ApiConstants.SET_VOICE_URL, params);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		ResultError resultError=parseResultError(result);
		logger.info("error:"+resultError.getError()+" error_description:"+resultError.getErrorDescription());
		
		return resultError;
	}
	
	public static ResultError cancelVoiceRequest(String machineCode,Integer aid){
		
		Map<String,String> params=new HashMap<String,String>();
		params.put(ApiConstants.MACHINE_CODE_PARAM_NAME, machineCode);
		params.put(ApiConstants.ACCESS_TOKEN_PARAM_NAME,getAccessToken());
		params.put(ApiConstants.AID_PARAM_NAME, aid.toString());
		setParams(params);
		
		String result=null;
		try {
			result=HttpClientUtils.postMethodRequest(ApiConstants.CANCEL_VOICE_URL, params);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		ResultError resultError=parseResultError(result);
		logger.info("error:"+resultError.getError()+" error_description:"+resultError.getErrorDescription());
		
		return resultError;
	}
	
	/**
	 * 
	 * TODO
	 * @author FEB
	 * @time 2018年9月12日 下午9:17:33
	 * @return ResultError
	 */
	public static ResultError setSoundRequest(String machineCode,String responseType,Integer voice){
		
		Map<String,String> params=new HashMap<String,String>();
		params.put(ApiConstants.MACHINE_CODE_PARAM_NAME, machineCode);
		params.put(ApiConstants.ACCESS_TOKEN_PARAM_NAME,getAccessToken());
		params.put(ApiConstants.RESPONSE_TYPE_PARAM_NAME, responseType);
		params.put(ApiConstants.VOICE_PARAM_NAME, voice.toString());
		setParams(params);
		
		String result=null;
		try {
			result=HttpClientUtils.postMethodRequest(ApiConstants.SET_SOUND_URL, params);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		ResultError resultError=parseResultError(result);
		logger.info("error:"+resultError.getError()+" error_description:"+resultError.getErrorDescription());
		
		return resultError;
	}
	
	/**
	 * 
	 * TODO
	 * @author FEB
	 * @time 2018年9月12日 下午9:18:06
	 * @return ResultError
	 */
	public static ResultError shutdownRestartRequest(String machineCode,String responseType){
		
		Map<String,String> params=new HashMap<String,String>();
		params.put(ApiConstants.MACHINE_CODE_PARAM_NAME, machineCode);
		params.put(ApiConstants.ACCESS_TOKEN_PARAM_NAME,getAccessToken());
		params.put(ApiConstants.RESPONSE_TYPE_PARAM_NAME, responseType);
		setParams(params);
		
		String result=null;
		try {
			result=HttpClientUtils.postMethodRequest(ApiConstants.SHUTDOWN_RESTART_URL, params);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		ResultError resultError=parseResultError(result);
		logger.info("error:"+resultError.getError()+" error_description:"+resultError.getErrorDescription());
		
		return resultError;
	}
	
	/**
	 * 
	 * TODO 设置LOGO
	 * @author FEB
	 * @time 2018年9月7日 下午4:21:53
	 * @return String
	 */
	public static String addPrintLogoRequest(String machineCode,String imgUrl){
		Map<String,String> params=new HashMap<String,String>();
		params.put(ApiConstants.MACHINE_CODE_PARAM_NAME, machineCode);
		params.put(ApiConstants.ACCESS_TOKEN_PARAM_NAME,getAccessToken());
		params.put(ApiConstants.IMG_URL_PARAM_NAME, imgUrl);
		setParams(params);
		
		String result=null;
		try {
			result=HttpClientUtils.postMethodRequest(ApiConstants.SET_PRINT_ICON_URL, params);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		ResultError resultError=parseResultError(result);
		logger.info("error:"+resultError.getError()+" error_description:"+resultError.getErrorDescription());
		
		return result;
	}
	
	/**
	 * 
	 * TODO 取消设置LOGO
	 * @author FEB
	 * @time 2018年9月7日 下午4:21:43
	 * @return String
	 */
	public static ResultError cancelPrintLogoRequest(String machineCode){
		Map<String,String> params=new HashMap<String,String>();
		params.put(ApiConstants.MACHINE_CODE_PARAM_NAME, machineCode);
		params.put(ApiConstants.ACCESS_TOKEN_PARAM_NAME,getAccessToken());
		setParams(params);
		
		String result=null;
		try {
			result=HttpClientUtils.postMethodRequest(ApiConstants.CANCEL_PRINT_ICON_URL, params);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		ResultError resultError=parseResultError(result);
		logger.info("error:"+resultError.getError()+" error_description:"+resultError.getErrorDescription());
		
		return resultError;
	}
	
	/**
	 * 
	 * TODO 获取终端状态
	 * @author FEB
	 * @time 2018年9月6日 下午11:38:11
	 * @return String
	 * @throws Exception 
	 */
	public static ResultError getPrintStatus(String machineCode){
		int result=-1;
		
		Map<String,String> params=new HashMap<String,String>();
		params.put(ApiConstants.MACHINE_CODE_PARAM_NAME, machineCode);
		params.put(ApiConstants.ACCESS_TOKEN_PARAM_NAME,getAccessToken());
		setParams(params);
		
		String json=null;
		try {
			json = HttpClientUtils.postMethodRequest(ApiConstants.PRINTER_STATUS_URL, params);
		} catch (Exception e) {
			e.printStackTrace();
		}
		ResultError resultError=parseResultError(json);
		logger.info("error:"+resultError.getError()+" error_description:"+resultError.getErrorDescription());
		
		
		return resultError;
	}
	
	
	
}
